今天,是鐵人賽第二十八天。
時間過得很快呢!
我們直接來看看吧。
上一篇,我們做完了 TODO List的 Model 部份,包含建模,以及建立其mongoDB,最後,我們也寫好了,之後會用到的CRUD檔案。
現在,我們要來看看,怎麼實作它在頁面呈現的部份。
因為,我們是以MVC的架構,來實作這個TODO List,那麼,我們必須做到關注點分離
的原則,來實作View這個部份。
因此,我們只要有資料,來做頁面的呈現即可!所以,我們要匯入資料。(暫時的)
我們可以先試做一個簡單的 app.js 讓它可以 render 我們匯入的資料,並且套用 jade樣版,使用bootstrap框架。
這個簡單的app.js 會像這樣:
app.js
var express = require('express');
var app = express();
var dataset=require('./recordset.js'); //要有資料來做頁面呈現, 所以直接匯入!
//set view engine
app.set("view engine","jade")
//set view directory
app.set("views",__dirname+"/views") // 樣版所在位置
app.get('/todo',function(req,res){
res.render('restfulTP',{itemlist:dataset}); // render 到 restful樣版
});
app.use('/restful',express.static(__dirname+'/public')); //一些必要的javascript, css皆放入此!!
app.listen(3000,function(){
console.log('Ready...for 3000');
});
如何使用bootstrap框架,變成jade,可以參考之前我們提過的 Day22 - Jade樣版的Layout
bootstrap的 icon 及 button,可以參考 bootstrap components
還有,好用的工具 幫我們的 html 語法 也轉成 jade,html2jade.org
另外,簡單的語法,可以使用這個工具測試 Jade Syntax Documentation
最後, restful.jade 完成 (有使用Layout)。
對照我們render後的結果,render 好的資料,會像下圖右方這樣:
所以,進入app 能看到的版面規劃好了,接下來我們要關注的,就是按下按鈕會發生什麼事
。
我們將分別為每個按鈕做說明。這裡使用 JQuery 語法做處理!
※ 這邊,要注意的是,pencial 以及 remove按鈕,是隨著 每一筆資料列 的產生而產生的,其按鈕所產生的id也會根據其資料id而相依。所以,我們將分做二個 .js 檔案,做按鈕事件的處理。
(pencial) 跳出一個編輯視窗,這個編輯視窗會有修改message 的地方,並且有存檔
及關閉
。(這邊要注意,將多2個按鈕)
關於編輯視窗,很幸運的,如果我們套用bootstrap樣版,它其實已經幫我們做好了。
所以,我們只要在 restful.jade 加入視窗的 jade 語法。
並且,為其(pencial) 按鈕設定 data-toggle=’modal’, data-target=’#myModal’ 指向視窗的 id。即可呈現它的功能!(相關技術可參考 bootstrap live-demo )
做好以後,會呈現如圖:
所以,pencial 這個按鈕,我們要做的事,就是把資料帶過去給 myModal 的 textarea裡,並且,在暗中傳送該筆的id,好讓存檔時,可以一併把資料送到後端(controller),做資料更新的處理。
(remove) 要能做到,取得該列的id,DELETE方式 回傳給 後端(我們可以叫它controller),做移除該筆資料的處理;並且,將結果 回傳至前端(比方,輸出一個刪除成功的訊息)。
我們直接看程式:
buttonlist.js
var reqdata={};
//做列表items button 的處理....
$('#itemset button').bind('click', function(){
// gets the id of a clicked button
var obj = $(this).attr('id');
var itemid='';
if(/pencil/.test(obj))
{
itemid=obj.replace(/pencil/gi,'');
var spancs='#itemset span.'+obj; //這筆按鈕的span 尋找方式字串。
var getmsg=$(spancs).text(); //取得所選的這筆資料。
$('#myModal').find($('#message-text')).val(getmsg); //把資料送給對話框裡的textbox
reqdata={'moid':itemid,'momsg':getmsg}; //把id記錄下來。
}
if(/remove/.test(obj)) //刪除...
{
itemid=obj.replace(/remove/gi,'');
reqdata={'moid':itemid};
//移除單一資料,直接做!!
//這裡寫delete ... url:'./restful/todo/1'
$.ajax({
url: '/restful/todo/'+reqdata.moid,
type: 'DELETE'
}).done(function(resp){
var oneset='div#record'+reqdata.moid;
$(oneset).remove();
alert(resp);
});
}
})
//做修改 儲存 button 的處理...
$('#myModal #saveitem').on('click',function(){
var postdata=$('#myModal').find($('#message-text')).val();
reqdata.momsg=postdata; //原先的資料會更改成這個...
//把資料送給後端做處理。
//這裡寫put ... url:'./restful/todo/1'
$.ajax({
url: '/restful/todo/'+reqdata.moid,
type: 'PUT',
data: reqdata
}).done(function(result){
var oneset='#itemset div#record'+reqdata.moid;
$(oneset).html(result); //更新完後,將結果覆蓋原本的div#recode+id
});
//將dialog隱藏
$('#myModal').modal('hide')
})
比較要注意的是修改儲存的部份,我們必須再新增一個 jade ,讓它專門能呈現一筆資料的部份(即,我們修改後的更新)。
oneTP.jade
- var fjo= "pencil" + oneid
- var fjk= "remove" + oneid
button.btn.btn-default.btn-xs(type='button', id=fjo, data-toggle='modal', data-target='#myModal')
span.glyphicon.glyphicon-pencil(aria-hidden='true')
button.btn.btn-default.btn-xs(type='button', id=fjk)
span.glyphicon.glyphicon-remove(aria-hidden='true')
span(class=fjo)=onemsg
p
script(src='./javascripts/buttonlist.js')
(plus) 要能做到,將MsgTB輸入新增的資料,POST 方式 送出給後端,做新增該筆message的處理;並且,將結果回傳至前端(比方,頁面多出了該筆新增的message)。
(retrieve) 要能做到,將MsgTB輸入的查詢關鍵字,GET方式 回傳給後端,做搜尋的處理;並將結果回傳至前端。
我們直接看程式:
restfuljs.js
var reqdata={};
//做新增 button 的處理...
$('#plus').on('click',function(){
reqdata={'momsg':$('#MsgTB').val()};
//把資料送給後端做處理。
//這裡寫post ... url:'./restful/todo'
$.ajax({
url: '/restful/todo',
type: 'post',
data: reqdata
}).done(function(result){
alert('ok!');
$('#itemset').html(result);
});
})
//做搜尋 button 的處理...
$('#search').on('click',function(){
reqdata={'momsg':$('#MsgTB').val()};
//把資料送給後端做處理。
//這裡寫get ... url:'./restful/todo/fasdfkmkmkoika'
$.ajax({
url: '/restful/todo/'+reqdata.momsg,
type: 'get'
}).done(function(result){
$("#itemset").html(result);
});
})
無論是新增或是搜尋,我們必須再新增一個 jade ,讓它專門能呈現多筆資料的部份(即將新資料結果覆蓋 itemset的地方!)
recodeTP.jade
for item in itemlist
- var foo= "pencil" + item.id
- var fkk= "remove" + item.id
- var rec= "record" + item.id
div(id=rec)
button.btn.btn-default.btn-xs(type='button', id=foo,
data-toggle='modal', data-target='#myModal')
span.glyphicon.glyphicon-pencil(aria-hidden='true')
button.btn.btn-default.btn-xs(type='button', id=fkk)
span.glyphicon.glyphicon-remove(aria-hidden='true')
span(class=foo)=item.message
p
script(src='./javascripts/buttonlist.js')
最後,我們來總整理一下。
我們總共有4個 jade檔案:
特別注意,每個 jade檔案分別載入的 js 檔,會寫在最下方!
ex. layout.jade
ex. restfulTP.jade
請將 jade 通通放在 ./views 資料夾裡。
並將 2個 .js 檔,放在 ./public/javascripts 資料夾裡。(當然,如果還有其他的js,都可進來,要注意路徑就是了!)
其他,像 .css 檔,放在 ./public/stylesheets 資料夾裡。
這邊,我們在TODO List 關於View的部份,講解到這裡。
明天,我們將進入 TODO List Controller的部份,完成這整個專案。